﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using PacManLib;

namespace PacManBoardControl
{
    /// <summary>
    /// Holds bitmaps for one of the ghosts.
    /// </summary>
    class GhostBitmapManager
    {
        #region Public methods and properties

        /// <summary>
        /// Constructor.
        /// </summary>
        public GhostBitmapManager(Color ghostColor)
        {
            m_ghostColor = ghostColor;
            generateGhostBitmaps();
        }

        /// <summary>
        /// Moves the ghost's legs to the next position.
        /// </summary>
        public void nextLegPosition()
        {
            m_legsIn = !m_legsIn;
        }

        /// <summary>
        /// Gets the bitmap to show.
        /// </summary>
        public Bitmap getBitmap(PlayerInfo ghostInfo)
        {
            // If the ghost is scared, we return the blue scared bitmap...
            if (ghostInfo.IsScared)
            {
                return m_bmpGhostScaredBlue1;
            }

            // The ghost is not scared, so the bitmap depends on the
            // direction that the ghost is heading and the position
            // of its legs...
            switch(ghostInfo.CurrentDirection)
            {
                case PlayerInfo.Direction.Up:
                    return m_legsIn ? m_bmpGhostUp1 : m_bmpGhostUp2;

                case PlayerInfo.Direction.Down:
                    return m_legsIn ? m_bmpGhostDown1 : m_bmpGhostDown2;
                
                case PlayerInfo.Direction.Left:
                    return m_legsIn ? m_bmpGhostLeft1 : m_bmpGhostLeft2;
                
                case PlayerInfo.Direction.Right:
                    return m_legsIn ? m_bmpGhostRight1 : m_bmpGhostRight2;
            }

            // This should not happen!
            return null;
        }

        #endregion

        #region Private functions

        /// <summary>
        /// Creates the bitmaps for the ghosts. 
        /// </summary>
        private void generateGhostBitmaps()
        {
            Graphics g;
            SolidBrush b = new SolidBrush(m_ghostColor);
            SolidBrush EyeBrush = new SolidBrush(Color.White);
            SolidBrush PupilBrush = new SolidBrush(Color.FromArgb(34, 32, 216));
            SolidBrush CoverBrush = new SolidBrush(Color.Black);
            SolidBrush ScaredBody1Brush = new SolidBrush(Color.FromArgb(33, 33, 222));
            SolidBrush ScaredBody2Brush = new SolidBrush(Color.FromArgb(222, 222, 222));
            SolidBrush ScaredFace1Brush = new SolidBrush(Color.FromArgb(241, 175, 155));
            SolidBrush ScaredFace2Brush = new SolidBrush(Color.FromArgb(255, 0, 0));

            Point p = new Point(-1, -1);

            Bitmap bmpCharBase = new Bitmap(GHOST_WIDTH, GHOST_HEIGHT);
            bmpCharBase = new Bitmap(GHOST_WIDTH, GHOST_HEIGHT);
            g = Graphics.FromImage(bmpCharBase);
            g.SmoothingMode = SmoothingMode.AntiAlias;
            g.FillEllipse(b, p.X + 3, p.Y, GHOST_WIDTH - 4, GHOST_HEIGHT - 2);
            g.FillRectangle(b, p.X + 3, p.Y + GHOST_HEIGHT / 2 - 1, GHOST_WIDTH - 4, GHOST_HEIGHT / 2);

            // Character Down 1
            m_bmpGhostDown1 = (Bitmap)bmpCharBase.Clone();
            g = Graphics.FromImage(m_bmpGhostDown1);
            g.SmoothingMode = SmoothingMode.AntiAlias;
            g.FillPie(CoverBrush, p.X + 3, p.Y + GHOST_HEIGHT - 11, 10, 11, 45, 90);
            g.FillRectangle(CoverBrush, p.X + (GHOST_WIDTH / 2 - 1), p.Y + GHOST_HEIGHT - 5, 4, 5);
            g.FillPie(CoverBrush, p.X + GHOST_WIDTH - 11, p.Y + GHOST_HEIGHT - 11, 10, 11, 45, 90);
            g.FillEllipse(EyeBrush, p.X + 7, p.Y + 10, 7, 10);
            g.FillEllipse(PupilBrush, p.X + 8, p.Y + 15, 5, 5);
            g.FillEllipse(EyeBrush, p.X + 17, p.Y + 10, 7, 10);
            g.FillEllipse(PupilBrush, p.X + 18, p.Y + 15, 5, 5);
            m_bmpGhostDown1.MakeTransparent(Color.Black);

            // Character Down 2
            m_bmpGhostDown2 = (Bitmap)bmpCharBase.Clone();
            g = Graphics.FromImage(m_bmpGhostDown2);
            g.SmoothingMode = SmoothingMode.AntiAlias;
            g.FillPie(CoverBrush, p.X - 4, p.Y + GHOST_HEIGHT - 11, 10, 11, 45, 90);
            g.FillPie(CoverBrush, p.X + 6, p.Y + GHOST_HEIGHT - 11, 10, 11, 45, 90);
            g.FillPie(CoverBrush, p.X + GHOST_WIDTH - 14, p.Y + GHOST_HEIGHT - 11, 10, 11, 45, 90);
            g.FillPie(CoverBrush, p.X + GHOST_WIDTH - 4, p.Y + GHOST_HEIGHT - 11, 10, 11, 45, 90);
            g.FillEllipse(EyeBrush, p.X + 7, p.Y + 10, 7, 10);
            g.FillEllipse(PupilBrush, p.X + 8, p.Y + 15, 5, 5);
            g.FillEllipse(EyeBrush, p.X + 17, p.Y + 10, 7, 10);
            g.FillEllipse(PupilBrush, p.X + 18, p.Y + 15, 5, 5);
            m_bmpGhostDown2.MakeTransparent(Color.Black);

            // Character Up 1
            m_bmpGhostUp1 = (Bitmap)bmpCharBase.Clone();
            g = Graphics.FromImage(m_bmpGhostUp1);
            g.SmoothingMode = SmoothingMode.AntiAlias;
            g.FillPie(CoverBrush, p.X + 3, p.Y + GHOST_HEIGHT - 11, 10, 11, 45, 90);
            g.FillRectangle(CoverBrush, p.X + (GHOST_WIDTH / 2 - 1), p.Y + GHOST_HEIGHT - 5, 4, 5);
            g.FillPie(CoverBrush, p.X + GHOST_WIDTH - 11, p.Y + GHOST_HEIGHT - 11, 10, 11, 45, 90);
            g.FillEllipse(EyeBrush, p.X + 7, p.Y + 2, 7, 10);
            g.FillEllipse(PupilBrush, p.X + 8, p.Y + 2, 5, 5);
            g.FillEllipse(EyeBrush, p.X + 17, p.Y + 2, 7, 10);
            g.FillEllipse(PupilBrush, p.X + 18, p.Y + 2, 5, 5);
            m_bmpGhostUp1.MakeTransparent(Color.Black);

            // Character Up 2
            m_bmpGhostUp2 = (Bitmap)bmpCharBase.Clone();
            g = Graphics.FromImage(m_bmpGhostUp2);
            g.SmoothingMode = SmoothingMode.AntiAlias;
            g.FillPie(CoverBrush, p.X - 4, p.Y + GHOST_HEIGHT - 11, 10, 11, 45, 90);
            g.FillPie(CoverBrush, p.X + 6, p.Y + GHOST_HEIGHT - 11, 10, 11, 45, 90);
            g.FillPie(CoverBrush, p.X + GHOST_WIDTH - 14, p.Y + GHOST_HEIGHT - 11, 10, 11, 45, 90);
            g.FillPie(CoverBrush, p.X + GHOST_WIDTH - 4, p.Y + GHOST_HEIGHT - 11, 10, 11, 45, 90);
            g.FillEllipse(EyeBrush, p.X + 7, p.Y + 2, 7, 10);
            g.FillEllipse(PupilBrush, p.X + 8, p.Y + 2, 5, 5);
            g.FillEllipse(EyeBrush, p.X + 17, p.Y + 2, 7, 10);
            g.FillEllipse(PupilBrush, p.X + 18, p.Y + 2, 5, 5);
            m_bmpGhostUp2.MakeTransparent(Color.Black);

            // Character Left 1
            m_bmpGhostLeft1 = (Bitmap)bmpCharBase.Clone();
            g = Graphics.FromImage(m_bmpGhostLeft1);
            g.SmoothingMode = SmoothingMode.AntiAlias;
            g.FillPie(CoverBrush, p.X + 3, p.Y + GHOST_HEIGHT - 11, 10, 11, 45, 90);
            g.FillRectangle(CoverBrush, p.X + (GHOST_WIDTH / 2 - 1), p.Y + GHOST_HEIGHT - 5, 4, 5);
            g.FillPie(CoverBrush, p.X + GHOST_WIDTH - 11, p.Y + GHOST_HEIGHT - 11, 10, 11, 45, 90);
            g.FillEllipse(EyeBrush, p.X + 5, p.Y + 5, 7, 10);
            g.FillEllipse(PupilBrush, p.X + 5, p.Y + 9, 5, 5);
            g.FillEllipse(EyeBrush, p.X + 15, p.Y + 5, 7, 10);
            g.FillEllipse(PupilBrush, p.X + 15, p.Y + 9, 5, 5);
            m_bmpGhostLeft1.MakeTransparent(Color.Black);

            // Character Left 2
            m_bmpGhostLeft2 = (Bitmap)bmpCharBase.Clone();
            g = Graphics.FromImage(m_bmpGhostLeft2);
            g.SmoothingMode = SmoothingMode.AntiAlias;
            g.FillPie(CoverBrush, p.X - 4, p.Y + GHOST_HEIGHT - 11, 10, 11, 45, 90);
            g.FillPie(CoverBrush, p.X + 6, p.Y + GHOST_HEIGHT - 11, 10, 11, 45, 90);
            g.FillPie(CoverBrush, p.X + GHOST_WIDTH - 14, p.Y + GHOST_HEIGHT - 11, 10, 11, 45, 90);
            g.FillPie(CoverBrush, p.X + GHOST_WIDTH - 4, p.Y + GHOST_HEIGHT - 11, 10, 11, 45, 90);
            g.FillEllipse(EyeBrush, p.X + 5, p.Y + 5, 7, 10);
            g.FillEllipse(PupilBrush, p.X + 5, p.Y + 9, 5, 5);
            g.FillEllipse(EyeBrush, p.X + 15, p.Y + 5, 7, 10);
            g.FillEllipse(PupilBrush, p.X + 15, p.Y + 9, 5, 5);
            m_bmpGhostLeft2.MakeTransparent(Color.Black);

            // Character Right 1
            m_bmpGhostRight1 = (Bitmap)bmpCharBase.Clone();
            g = Graphics.FromImage(m_bmpGhostRight1);
            g.SmoothingMode = SmoothingMode.AntiAlias;
            g.FillPie(CoverBrush, p.X + 3, p.Y + GHOST_HEIGHT - 11, 10, 11, 45, 90);
            g.FillRectangle(CoverBrush, p.X + (GHOST_WIDTH / 2 - 1), p.Y + GHOST_HEIGHT - 5, 4, 5);
            g.FillPie(CoverBrush, p.X + GHOST_WIDTH - 11, p.Y + GHOST_HEIGHT - 11, 10, 11, 45, 90);
            g.FillEllipse(EyeBrush, p.X + 10, p.Y + 5, 7, 10);
            g.FillEllipse(PupilBrush, p.X + 13, p.Y + 9, 5, 5);
            g.FillEllipse(EyeBrush, p.X + 20, p.Y + 5, 7, 10);
            g.FillEllipse(PupilBrush, p.X + 23, p.Y + 9, 5, 5);
            m_bmpGhostRight1.MakeTransparent(Color.Black);

            // Character Right 2
            m_bmpGhostRight2 = (Bitmap)bmpCharBase.Clone();
            g = Graphics.FromImage(m_bmpGhostRight2);
            g.SmoothingMode = SmoothingMode.AntiAlias;
            g.FillPie(CoverBrush, p.X - 4, p.Y + GHOST_HEIGHT - 11, 10, 11, 45, 90);
            g.FillPie(CoverBrush, p.X + 6, p.Y + GHOST_HEIGHT - 11, 10, 11, 45, 90);
            g.FillPie(CoverBrush, p.X + GHOST_WIDTH - 14, p.Y + GHOST_HEIGHT - 11, 10, 11, 45, 90);
            g.FillPie(CoverBrush, p.X + GHOST_WIDTH - 4, p.Y + GHOST_HEIGHT - 11, 10, 11, 45, 90);
            g.FillEllipse(EyeBrush, p.X + 10, p.Y + 5, 7, 10);
            g.FillEllipse(PupilBrush, p.X + 13, p.Y + 9, 5, 5);
            g.FillEllipse(EyeBrush, p.X + 20, p.Y + 5, 7, 10);
            g.FillEllipse(PupilBrush, p.X + 23, p.Y + 9, 5, 5);
            m_bmpGhostRight2.MakeTransparent(Color.Black);

            // Character Scared Blue 1
            m_bmpGhostScaredBlue1 = new Bitmap(GHOST_WIDTH, GHOST_HEIGHT);
            g = Graphics.FromImage(m_bmpGhostScaredBlue1);
            g.SmoothingMode = SmoothingMode.AntiAlias;
            g.FillEllipse(ScaredBody1Brush, p.X + 3, p.Y, GHOST_WIDTH - 4, GHOST_HEIGHT - 2);
            g.FillRectangle(ScaredBody1Brush, p.X + 3, p.Y + GHOST_HEIGHT / 2 - 1, GHOST_WIDTH - 4, GHOST_HEIGHT / 2);
            g.FillPie(CoverBrush, p.X + 3, p.Y + GHOST_HEIGHT - 11, 10, 11, 45, 90);
            g.FillRectangle(CoverBrush, p.X + (GHOST_WIDTH / 2 - 1), p.Y + GHOST_HEIGHT - 5, 4, 5);
            g.FillPie(CoverBrush, p.X + GHOST_WIDTH - 11, p.Y + GHOST_HEIGHT - 11, 10, 11, 45, 90);
            g.FillRectangle(ScaredFace1Brush, p.X + 10, p.Y + 11, 4, 4);
            g.FillRectangle(ScaredFace1Brush, p.X + 18, p.Y + 11, 4, 4);
            g.DrawArc(new Pen(ScaredFace1Brush, 1), p.X + 5, p.Y + 20, 5, 4, 180, 160);
            g.DrawArc(new Pen(ScaredFace1Brush, 1), p.X + 9, p.Y + 18, 5, 4, 20, 160);
            g.DrawArc(new Pen(ScaredFace1Brush, 1), p.X + 13, p.Y + 20, 6, 4, 200, 140);
            g.DrawArc(new Pen(ScaredFace1Brush, 1), p.X + 18, p.Y + 18, 5, 4, 40, 140);
            g.DrawArc(new Pen(ScaredFace1Brush, 1), p.X + 22, p.Y + 20, 5, 4, 200, 160);

            b.Dispose();
            CoverBrush.Dispose();
            EyeBrush.Dispose();
            PupilBrush.Dispose();
        }

        #endregion

        #region Constants

        // The size of the ghost bitmap...
        private const int GHOST_WIDTH = 30;
        private const int GHOST_HEIGHT = 30;

        #endregion

        #region Private data

        // Ghost bitmaps...
        private Bitmap m_bmpGhostUp1;
        private Bitmap m_bmpGhostUp2;
        private Bitmap m_bmpGhostLeft1;
        private Bitmap m_bmpGhostLeft2;
        private Bitmap m_bmpGhostRight1;
        private Bitmap m_bmpGhostRight2;
        private Bitmap m_bmpGhostDown1;
        private Bitmap m_bmpGhostDown2;
        private Bitmap m_bmpGhostScaredBlue1;

        // The color of the ghost...
        private Color m_ghostColor;

        // A bool which toggles the ghost's leg position...
        private bool m_legsIn = true;

        #endregion
    }
}
